<template>
  <div class="properties-panel">
    <el-tabs v-model="activeTab">
      <el-tab-pane label="组件配置" name="component">
    <div class="panel-section">
      <div v-if="selectedIds.length > 0" >
        <!-- 多选编辑 -->
        <div v-if="selectedIds.length > 1" class="multi-edit">
          <el-alert
            title="批量编辑模式"
            :description="descriptionText"
            type="info"
            :closable="false"
            style="margin-bottom: 16px;"
          />
		  <ComponentEventPane type="group" :structure="structureTree" :bindings="localGroupBindings||[]" @bindings="handleGroupBindings"/>
        </div>
        <!-- 单选编辑 -->
        <div v-else-if="selectedComponent" class="single-edit">
          <ComponentConfigPanel 
            :component="currentConfigData"
			:structure="structureTree"
            @config-change="handleComponentConfigChange"
          />
        </div>
      </div>
      <div v-else class="no-component-selected">
        <i class="el-icon-info"></i>
        <p>请选择设计区域中的组件进行配置</p>
      </div>
    </div>
	
	</el-tab-pane>
	<el-tab-pane label="页面设置" name="page">
        <div class="panel-section">
			<el-collapse expand-icon-position="left">
			  <el-collapse-item title="基础" name="page-config">
				<el-scrollbar height="calc(100vh - 210px)">
				  <el-form  @submit.prevent label-position="top" style="padding: 5px;">
					<el-form-item label="页面名称">
						  <el-input v-model="localPageTitle"  @change="emitPageTitleChange" controls-position="right"/>
					</el-form-item>
				
					<el-row :gutter="8" style="margin-bottom: 12px;">
					  <el-col :span="12">
						<el-form-item label="宽度">
						  <el-input-number v-model="localPageWidth" :min="320" :max="10000" @change="emitPageSizeChange" @input="emitPageSizeChange" controls-position="right"/>
						</el-form-item>
					  </el-col>
					  <el-col :span="12">
						<el-form-item label="高度">
						  <el-input-number v-model="localPageHeight" :min="200" :max="10000" @change="emitPageSizeChange" @input="emitPageSizeChange" controls-position="right"/>
					  </el-form-item>
					  </el-col>
					</el-row>
					
					<ImgField :baseUrl="BASE_API"
					:identifier="'hover'" 
					label="背景图片" 
					:value="pageBgImg" 
					@onchange="onchange"  />
					<el-button v-if="pageBgImg" size="small" @click="clearBgImg" style="margin-top: -5px; margin-bottom: 8px;">清除背景</el-button>
					
					<el-form-item label="背景颜色">
					  <el-color-picker v-model="localPageBgColor" @change="emitBgColorChange" />
					</el-form-item>
					<el-form-item label="适配方式">
					  <el-radio-group v-model="fitMode" @change="emitFitModeChange">
						<el-radio-button :value="'contain'">自适应</el-radio-button>
						<el-radio-button :value="'cover'">填充</el-radio-button>
						<el-radio-button :value="'stretch'">拉伸</el-radio-button>
						<el-radio-button :value="'center'">居中</el-radio-button>
					  </el-radio-group>
					</el-form-item>
					<el-form-item label="滤镜">
					  <el-switch v-model="filterEnabled" />
					</el-form-item>
					<div v-if="filterEnabled" class="filter-section">
					  <el-form-item label="色相">
						<el-slider v-model="filter.hue" :min="0" :max="360" :step="1" show-input />
					  </el-form-item>
					  <el-form-item label="饱和度">
						<el-slider v-model="filter.saturate" :min="0" :max="200" :step="1" show-input />
					  </el-form-item>
					  <el-form-item label="对比度">
						<el-slider v-model="filter.contrast" :min="0" :max="200" :step="1" show-input />
					  </el-form-item>
					  <el-form-item label="亮度">
						<el-slider v-model="filter.brightness" :min="0" :max="200" :step="1" show-input />
					  </el-form-item>
					  <el-form-item label="透明度">
						<el-slider v-model="filter.opacity" :min="0" :max="100" :step="1" show-input />
					  </el-form-item>
					</div>
					<el-form-item label="主题色">
					  <div class="theme-color-list">
						<div v-for="color in themeColors" :key="color" :style="{background: color}" class="theme-color-item" :class="{active: color === localThemeColor}" @click="selectThemeColor(color)"></div>
					  </div>
					</el-form-item>
				  </el-form>
				  <el-alert type="warning" show-icon style="margin-top: 10px;" :closable="false">
					若预览时大屏模糊，可以尝试关闭滤镜进行修复
				  </el-alert>
				</el-scrollbar>
			  </el-collapse-item>
			  <el-collapse-item title="事件" name="page-event">
				  <ComponentEventPane type="page" :structure="structureTree" :bindings="localPageBindings||[]" @bindings="handleBindings"/>
			  </el-collapse-item>
			</el-collapse>		
		</div>
    </el-tab-pane>
	
    <el-tab-pane label="页面结构" name="structure">
        <div class="panel-section">
        <el-scrollbar height="calc(100vh - 160px)">
          <el-tree
            :data="structureTree"
            :props="treeProps"
            node-key="id"
            highlight-current
            default-expand-all
			:show-checkbox="false"
			:check-on-click-node="true"
			:check-strictly="false"
            @node-click="handleNodeClick"
            @node-contextmenu="(event: MouseEvent, data: any, _node: any)=>{
				emit('menu:context', event, data, _node)
			}"
            style="background:transparent;"
          >
            <template #default="{ data }">
              <span>
                <i v-if="data.type==='group'" class="el-icon-folder"></i>
                <i v-else class="el-icon-box"></i>
                {{ data.label }}
              </span>
            </template>
          </el-tree>
		</el-scrollbar>
		</div>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, computed, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import ComponentConfigPanel from '@/views/visual-app/project/edit/widget/ComponentConfigPanel.vue'
import ComponentEventPane from '@/components/visual/widget/ComponentEventPane.vue'
import type { PageFilter, PropertiesPanelProps, ComponentInstance, ComponentGroup } from '@/types/visual-app'
import type { CSSProperties } from 'vue'
import { useVisualStore } from '@/store/visual'
const dynamicVisualStore = useVisualStore()
import { axiosInstance } from '@/utils/http/index'
const BASE_API = axiosInstance.defaults.baseURL

const props = defineProps<PropertiesPanelProps & {
  selectedComponent: ComponentInstance | null
  components: ComponentInstance[]
  groups: ComponentGroup[]
}>()

const emit = defineEmits([
  'update:pageTitle',
  'update:pageSize',
  'update:pageBgColor',
  'update:pageBgImg',
  'update:fitMode',
  'update:filter',
  'update:themeColor',
  'update:pageBindings',
  'selectComponentById',
  'selectGroupById',
  'update:groupBindings',
  'menu:context',
])
const activeTab = ref('component')

// 批量编辑本地变量
const localBatchBgColor = ref(props.batchBgColor)
const localBatchWidth = ref(props.batchWidth)
const localBatchHeight = ref(props.batchHeight)
watch(() => props.batchBgColor, val => { localBatchBgColor.value = val })
watch(() => props.batchWidth, val => { localBatchWidth.value = val })
watch(() => props.batchHeight, val => { localBatchHeight.value = val })
watch(localBatchBgColor, val => { props.batchUpdateBgColor && props.batchUpdateBgColor(val) })
watch([localBatchWidth, localBatchHeight], ([w, h]) => { props.batchUpdateSize && props.batchUpdateSize(w, h) })
watch(() => props.pageBindings, val => { localPageBindings.value = (Array.isArray(val) ? [...val] : []) })

// 页面设置相关本地状态
const localPageTitle = ref('')
const localPageWidth = ref(1920)
const localPageHeight = ref(1080)
const localPageBgColor = ref('#1a2b4c')
const localPageBindings = ref<any[]>([])
const pageBgImg = ref<string | null>('')
const fitMode = ref('contain')
const filterEnabled = ref(false)
const filter = ref({
  hue: 0,
  saturate: 100,
  contrast: 100,
  brightness: 100,
  opacity: 100
})
const themeColors = [
  '#409EFF', '#67C23A', '#E6A23C', '#F56C6C', '#8A2BE2', '#00BFFF', '#FF69B4', '#FFA500', '#00C853', '#00B8D4'
]
const localThemeColor = ref(themeColors[0])

const localGroupBindings = ref<any[]>([])

watch(() => props.selectedGroup, val => { 
	if(val){
		localGroupBindings.value=val.bindings || []
	}else{
		localGroupBindings.value= []
	}
})

// 结构树属性
const treeProps = { label: 'label', children: 'children' }
// 生成页面结构树
const structureTree = computed(() => {
  // 先分组，再组件
  const groupMap: Record<string, any> = {}
  if (Array.isArray(props.groups)) {
    props.groups.forEach((g: any) => {
      groupMap[g.id] = {
        id: g.id,
        label: g.name,
        type: 'group',
        children: [],
		raw: g
      }
    })
  }
  
  const nodes: any[] = []
  if (Array.isArray(props.components)) {
    props.components.forEach((c: any) => {
      if (c.groupId && groupMap[c.groupId]) {
        groupMap[c.groupId].children.push({
          id: c.id,
          label: c.title || c.type,
          type: 'component',
		  componentId: c.componentId,
          raw: c
        })
      } else {
        nodes.push({
          id: c.id,
          label: c.title || c.type,
          type: 'component',
		  componentId: c.componentId,
          raw: c
        })
      }
    })
  }
  // 分组节点放前面
  return [
    ...Object.values(groupMap),
    ...nodes
  ]
})

const descriptionText = computed(() => 
  `已选择 ${props.selectedIds.length} 个组件，修改属性将应用到所有选中组件`
)

function handleNodeClick(data: any) {
  if (data.type === 'component') {
    emit('selectComponentById', data.raw.id)
  } else if (data.type === 'group') {
    emit('selectGroupById', data.id.replace('group-', ''))
  }
}

// watch props 同步到本地状态
watch(() => props.pageSize, (val) => {
  if (typeof val === 'string' && val.includes('x')) {
    const [w, h] = val.split('x').map(Number)
    localPageWidth.value = w
    localPageHeight.value = h
  }
}, { immediate: true })

watch(() => props.pageBgColor, (val) => {
  localPageBgColor.value = val
}, { immediate: true })
watch(() => props.pageBgImg, (val) => {
  pageBgImg.value = val
}, { immediate: true })
watch(() => props.fitMode, (val) => {
  fitMode.value = val
}, { immediate: true })
watch(() => props.filter, (val) => {
  filter.value = { ...val }
}, { immediate: true, deep: true })
watch(() => props.themeColor, (val) => {
  localThemeColor.value = val
}, { immediate: true })
watch(() => props.pageTitle, (val) => {
  localPageTitle.value = val
}, { immediate: true })


function emitPageSizeChange() {
  emit('update:pageSize', `${localPageWidth.value}x${localPageHeight.value}`)
}
function emitBgColorChange() {
  emit('update:pageBgColor', localPageBgColor.value)
}
function emitPageTitleChange() {
  emit('update:pageTitle', localPageTitle.value)
}

const onchange = (input: { pidentifier: string, identifier: string, value: any }) => {
	 pageBgImg.value = input.value
	emit('update:pageBgImg', pageBgImg.value)
}

function clearBgImg() {
  pageBgImg.value = ''
  emit('update:pageBgImg', '')
}

function emitFitModeChange() {
  emit('update:fitMode', fitMode.value)
}

watch(filter, (val) => {
  emit('update:filter', val)
}, { deep: true })

function selectThemeColor(color: string) {
  localThemeColor.value = color
  emit('update:themeColor', color)
}




function isGroupLocked(groupId: string|null) {
	if (!groupId) return false;
	const group = props.groups.find(g => g.id === groupId);
	return !!group?.locked;
}

const currentConfigData = ref({} as ComponentInstance);
watch(() => props.selectedComponent, (val) => {
  if (val && val.componentId) {
    currentConfigData.value = val;
  }
}, { immediate: true });


const handleBindings=(bindings:any)=>{
	emit('update:pageBindings', bindings)
}

const handleGroupBindings=(bindings:any)=>{
	emit('update:groupBindings', bindings)
	localGroupBindings.value=bindings;
}


function handleComponentConfigChange(field:{key:string,value:Object}) {
	console.log(field);
}

function deepAssign(target: any, source: any, visited = new WeakSet()) {
  // 检查循环引用
  if (visited.has(source)) {
    return
  }
  visited.add(source)
  
  Object.keys(source).forEach(key => {
    if (
      typeof source[key] === 'object' &&
      source[key] !== null &&
      !Array.isArray(source[key]) &&
      typeof target[key] === 'object' &&
      target[key] !== null &&
      !Array.isArray(target[key])
    ) {
      // 确保目标对象存在
      if (!target[key]) {
        target[key] = {}
      }
      deepAssign(target[key], source[key], visited)
    } else {
      target[key] = source[key]
    }
  })
}


</script>

<style scoped>
.properties-panel {
  width: 380px;
  background: var(--panel-bg);
  border-left: 1px solid var(--border-color);
  padding: 0;
  overflow-y: auto;
}
.bg-uploader {
  width: 100%;
  min-height: 120px;
  border: 1.5px dashed #dcdfe6;
  border-radius: 8px;
  background: #fafbfc;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin-bottom: 8px;
  cursor: pointer;
}
.bg-upload-icon {
  font-size: 48px;
  color: #d3d3d3;
  margin: 24px 0 8px 0;
}
.bg-preview {
  max-width: 100%;
  max-height: 100px;
  margin: 8px 0;
  border-radius: 6px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
.theme-color-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 4px;
}
.theme-color-item {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  transition: border 0.2s;
}
.theme-color-item.active {
  border: 2px solid #409EFF;
  box-shadow: 0 0 6px #409EFF44;
}
.filter-section {
  background: #f6f8fa;
  border-radius: 6px;
  padding: 10px 8px 2px 8px;
  margin-bottom: 8px;
}
  .panel-section {
    margin-bottom: 20px;
    /* padding: 18px 15px 15px 15px; */
    border-bottom: 1px solid var(--border-color);
  }
  .panel-title {
    display: flex;
    align-items: center;
    margin-bottom: 15px;
    color: #a0b1e0;
}
.panel-title i {
      margin-right: 8px;
    }
  .no-component-selected, .property-form {
    background: rgba(30, 60, 128, 0.1);
    border-radius: 4px;
    padding: 20px;
    text-align: center;
    color: #a0b1e0;
}
.no-component-selected i, .property-form i {
  font-size: 36px;
  margin-bottom: 10px;
  opacity: 0.7;
}
.property-form {
	text-align: left;
}


</style> 